/**
 * @file bull_hal_sys_thread.c
 * @brief 
 * @author yejing (yejh@gongniu.cn)
 * @version 1.0
 * @date 2024-05-09
 * 
 * Copyright 2021-2023 GongNiu Inc. All Rights Reserved.
 * 
 */

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "bull_hal_sys_thread.h"


/***********************************************************
*************************variable define********************
***********************************************************/



/**
 * @brief 创建线程
 * @param  thrd_param       My Param doc
 * @return int 
 */
OPERATE_RET bull_hal_sys_thread_create( THREAD_FUNC_T func, const char* name, unsigned int stack_size, void* arg, unsigned int priority, THREAD_HANDLE* thread )
{
    BaseType_t ret = 0;
    ret = xTaskCreate(func, name, stack_size/sizeof(portSTACK_TYPE), (void*)arg, priority, ( TaskHandle_t *)thread );
    if (ret != pdPASS) {
        return OPRT_OS_ADAPTER_THRD_CREAT_FAILED;
    }

    return OPRT_OS_ADAPTER_OK;
}

/**
 * @brief 删除线程
 * @param  thread  线程句柄
 */
OPERATE_RET bull_hal_sys_thread_delete( THREAD_HANDLE thread )
{
     vTaskDelete(thread);

     return OPRT_OS_ADAPTER_OK;
}


/**
 * @brief 创建spiram线程
 * @param  thrd_param 内存创建在外部spiram
 * @return int 
 * @note  spiram使用外部堆栈，任务内不能进行外部flash的读写操作
 */
OPERATE_RET bull_hal_sys_thread_spiram_create( THREAD_FUNC_T func, const char* name, unsigned int stack_size, void* arg, unsigned int priority, THREAD_HANDLE* thread )
{
    BaseType_t ret = 0;
    ret = xTaskCreateWithCaps(func, name, stack_size/sizeof(portSTACK_TYPE), (void*)arg, priority, ( TaskHandle_t *)thread, MALLOC_CAP_SPIRAM );
    if (ret != pdPASS) {
        return OPRT_OS_ADAPTER_THRD_CREAT_FAILED;
    }

    return OPRT_OS_ADAPTER_OK;
}

/**
 * @brief 删除spiram线程
 * @param  thread  线程句柄
 */
OPERATE_RET bull_hal_sys_thread_spiram_delete( THREAD_HANDLE thread )
{
     vTaskDeleteWithCaps(thread);

     return OPRT_OS_ADAPTER_OK;
}

/**
 * @brief 判断传入进去的任务句柄是否为当前任务
 * @return THREAD 
 */
OPERATE_RET bull_hal_sys_thread_is_self( THREAD_HANDLE thread, BOOL_T* is_self )
{
    if (NULL == thread || NULL == is_self) {
        return OPRT_OS_ADAPTER_INVALID_PARM;
    }

    THREAD_HANDLE self_handle = xTaskGetCurrentTaskHandle();
    if (NULL == self_handle) {
        return OPRT_OS_ADAPTER_THRD_JUDGE_SELF_FAILED;
    }

    *is_self = (thread == self_handle);

    return OPRT_OS_ADAPTER_OK;
}


/**
 * @brief get thread stack's watermark
 * 
 * @param[in] thread    the thread handle
 * @param[out] watermark  watermark in Bytes
 * @retval OPRT_OK      success
 * @retval Other        fail
 */
OPERATE_RET bull_hal_sys_thread_get_stack_hight_watermark( THREAD_HANDLE thread, UINT_T* watermark )
{
    if (NULL == thread || NULL == watermark) {
        return OPRT_OS_ADAPTER_INVALID_PARM;
    }

    *watermark = uxTaskGetStackHighWaterMark(thread) * sizeof(UBaseType_t);

    return OPRT_OS_ADAPTER_OK;
}



/**
* @brief set thread priority
*
* @param[in] thread       the input thread handle
* @param[in] prio_thread  the priority thread send to
* @retval void
*/
void bull_hal_sys_thread_set_priority( THREAD_HANDLE thread, INT_T prio_thread )
{
    vTaskPrioritySet(thread, prio_thread);
}


/**
* @brief get thread priority
*
* @param[in]  thread     the input thread handle
* @param[out] priority   the priority of thread
* @retval void
*/
INT_T bull_hal_sys_thread_get_priority( THREAD_HANDLE thread )
{
    return uxTaskPriorityGet(thread);
}





